/***************************************************************************
 *   Copyright (C) 2008 by Silvan Imsand <imsandli@gmail.com>              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

package com.sametime.twitterclient.twitterapi;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;

import com.sametime.twitterclient.Activator;
import com.sametime.twitterclient.preferences.PreferenceConstants;


/**
 * This class is the connetion between the TwitterView and the TwitterAPI
 * As twitter.com is limited in the amount of querys, we cache all the data
 * we receive.
 * 
 * This class is also responsible for regulary asking twitter for new Data
 * and fetching/caching the images from the different twitter-user
 * 
 * @since 1.0
 * @author Silvan Imsand
 */
public class TwitterData {
	private final static TwitterData INSTANCE = new TwitterData();
	static ListenerList twitterListeners = new ListenerList();
	private Timer timer = new Timer();
	private String userName = null;
	private String password= null;
	private TwitterAPI twitter;
	
	private List recentStatus = Collections.synchronizedList(new ArrayList());
	private Map imageCache = Collections.synchronizedMap(new HashMap());
	
	// Last UserMessage
	private TwitterStatus twitterStatus = new TwitterStatus();
	
	
	
	public static void addRefreshListener(ITwitterListener listener) {
		twitterListeners.add(listener);
	}

	public static void fireRefreshEvent(TwitterStatus status) {
		Object[] listeners = twitterListeners.getListeners();
		for (int i = 0; i < listeners.length; i++) {
			((ITwitterListener) listeners[i]).handleTwitterRefresh();
			((ITwitterListener) listeners[i]).setUserStatus(status);
		}
	}
	
	public static void fireError(String message) {
		Object[] listeners = twitterListeners.getListeners();
		for (int i = 0; i < listeners.length; i++) {
			((ITwitterListener) listeners[i]).setErrorMessage(message);
		}
	}	
	
	public static void fireRefresh() {
		fireRefreshEvent(null);
	}

	public static void removeRefreshListener(ITwitterListener listener) {
		twitterListeners.remove(listener);
	}	
	
	
	/**
	 * returns the twitter reference
	 * @return
	 */
	public static TwitterData getInstance() {
		return INSTANCE;
	}

	/**
	 * private constructor. Get the refernce with <code>getInstance()</code>
	 */
	private TwitterData() {
		startTimer();
	}
	
	
	/**
	 * Stop any runnig Timer, and Sart a new timer with the 
	 * interval provided in the preferences.
	 * It will also start a refresh of the data with one second delay
	 */
	public void startTimer() {
		try {
			timer.cancel();
		} catch (Exception e) {
			// ignore exception
		}
		timer = new Timer();
		Preferences ps = Activator.getDefault().getPluginPreferences();
		int timeInMinutes = ps.getInt(PreferenceConstants.P_REFRESHLEVEL);
		if (timeInMinutes == 0) //without saved settings the value is zero
			timeInMinutes = 1;
		timer.schedule( new RefreshTask(), 1000, timeInMinutes*60*1000 );		
	}

	/**
	 * this method is responsible for fetching the data from twitter
	 * and will be started from the <code>refreshTask</code>
	 */
	private synchronized void refresh() {
		try {
			// reset imageCache if more then 30 images where saved (we fetch only 20 status)
			if (imageCache.size()>=30)
				imageCache.clear();
			
			// check for changed username and password
			Preferences ps = Activator.getDefault().getPluginPreferences();
			if (userName==null || userName != ps.getString(PreferenceConstants.P_USERNAME)
					|| password != ps.getString(PreferenceConstants.P_PASSWORD)) {
				userName = ps.getString(PreferenceConstants.P_USERNAME);
				password = ps.getString(PreferenceConstants.P_PASSWORD);
				twitter = new TwitterAPI(userName, password);			
			}
			
			// check if username and password are provided
			if (userName.equals("")||password.equals("")) {
				fireError("Please update the Twitter preference page");
				return;
			}			
			
			// get userdata if we don't already have it (cause of API checking limit)
			if (twitterStatus.getMessage()==null) {
				twitterStatus = twitter.getUserStatus();
			}
			
			// fill recentStatus
			recentStatus.clear();
			if (ps.getBoolean(PreferenceConstants.P_SHOWFRIENDS)) {
				// with friends
				recentStatus.addAll(twitter.getFriendsTimeline());
			} else {
				// without friends
				recentStatus.addAll(twitter.getUserTimeline());
			}

			fireRefreshEvent(twitterStatus);
//			System.out.println("TWITTER REFRESH");
		} catch (Exception e) {
			if (e.getMessage()!= null) {
				if (!twitter.isAuthenthicated()){
					fireError("Check username and password. Message from Twitter: " + e.getMessage());
				} else {
					fireError(e.getMessage());
				}
			} else {
				e.printStackTrace();
			}
		}		
	}
	

	/**
	 * Check, if the specific image is cached, otherwhise fetch the image from the web
	 * 
	 * @param imagePath
	 * @return
	 */
	public synchronized Image getImage(URI imagePath) {
		Image image;
		try {
			if (imageCache.containsKey(imagePath))
				return (Image)imageCache.get(imagePath);			
			image = ImageDescriptor.createFromURL(imagePath.toURL()).createImage();
			imageCache.put(imagePath, image);
		} catch (Exception e) {
			// problems while fetching images
			// return default image
			return Activator.getImageDescriptor("images/EmptyImage.gif").createImage();
		}
		return image;
	}


	
	/**
	 * Task for regulary refreshing the data from the web
	 * 
	 * @author Silvan Imsand
	 *
	 */
	private class RefreshTask extends TimerTask  
	{
	  public void run()  
	  {
	    refresh();
	  }
	}

	
	/**
	 * Method to send a new status to the twitter server
	 * @param msg new Status
	 */
	public synchronized void sendStatus(String msg) {
		try {
			twitterStatus = twitter.sendStatusUpdate(msg);
		} catch (Exception e) {
			if (e.getMessage()!= null) {
				fireError(e.getMessage());
			} else {
				e.printStackTrace();
			}
		}
	}

	
	/**
	 * @return the last user status
	 */
	public synchronized List getRecentStatus() {
		return recentStatus;
	}
		
}
